﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;

namespace Pg.BioMedics.SDR.Caching.Linq
{
    /// <summary>
    /// Provides logic for queries executing against specified cache
    /// </summary>
    public class DistributedCacheQueryable<T> : IQueryable<T>
    {
        #region Fields

        private DistributedCachingStrategy<T> cachingStrategy;
        private Expression expression;
        private IQueryProvider provider;

        #endregion

        #region Constructors

        /// <summary>
        /// Creates instance of cache query
        /// </summary>
        /// <param name="cache">Cache instance</param>
        internal DistributedCacheQueryable(DistributedCachingStrategy<T> cachingStrategy)
        {
            this.cachingStrategy = cachingStrategy;
            this.expression = Expression.Constant(this);
            this.provider = new DistributedCacheQueryProvider<T>(cachingStrategy);
        }

        internal DistributedCacheQueryable(DistributedCachingStrategy<T> cachingStrategy, Expression expression)
        {
            this.cachingStrategy = cachingStrategy;
            this.expression = expression;
            this.provider = new DistributedCacheQueryProvider<T>(cachingStrategy);
        }

        #endregion

        #region IEnumerable<T> Members

        public IEnumerator<T> GetEnumerator()
        {
            return (this.provider.Execute<IEnumerable<T>>(this.expression)).GetEnumerator();
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return (this.provider.Execute<System.Collections.IEnumerable>(this.expression)).GetEnumerator();
        }

        #endregion

        #region IQueryable Members

        /// <summary>
        /// Gets query execution result type
        /// </summary>
        public Type ElementType
        {
            get 
            { 
                return typeof(T); 
            }
        }

        /// <summary>
        /// Gets query expression
        /// </summary>
        public Expression Expression
        {
            get 
            {
                return this.expression;
            }
        }

        /// <summary>
        /// Gets query provider services by this query
        /// </summary>
        public IQueryProvider Provider
        {
            get 
            {
                return this.provider;
            }
        }

        #endregion
    }
}
